#!/usr/bin/env python

# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

""" Contains OAuth 2.0 Callback handler."""

import app_params as application_params
from lib.oauth2client.appengine import StorageByKeyName
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db 
import model
from lib import http
from lib.error import handle_error
import logging
from django.utils import simplejson as json
import utils
import os

__author__ = "Maciej Machulak"
__maintainer__ = "Maciej Machulak"
__email__ = "mmachulak@google.com"

__copyright__ = "Copyright 2011, Google Inc."
__license__ = "Apache License 2.0"
__version__ = "0.1"
__status__ = "Prototype"

class OAuthHandler(webapp.RequestHandler):

  def get(self):

      flow = application_params.IDP_FLOW
      credentials = flow.step2_exchange(self.request.params)
 
      if credentials is None:
        pass;
      access_token = credentials.access_token
      logging.debug('access token: %s',access_token)
      refresh_token = credentials.refresh_token
      logging.debug('refresh token; %s', refresh_token)

      # Access user information from user info endpoint
      url = application_params.IDPConfig.idp
      headers = { http.Header.authorization: http.Header.bearer + ' ' + access_token }
      params = {}
      user_info_path = application_params.IDPConfig.user_info_path
      response = http.get_request(url, user_info_path, headers, params)

      if response.status != 200:
        logging.error('invalid user info response from the server')
        handle_error(self)
        return    
      
      logging.debug('correct response status code from the server: %s' % response.status)  
     
      response_read = response.read()
      logging.debug('response %s ' % response_read)
      parsed_response = json.loads(response_read)
      logging.debug('user info response: %s ' % parsed_response)
      
      # Create user locally or retrieve existing user
      user_id = parsed_response['domain'] + parsed_response['user_id']
      user = model.User.all().filter('username = ', user_id).get()
      if user is None:
        logging.debug('creating new user')
        
        # Store user within DB
        user = model.User(
                username = user_id,
                display_name = parsed_response['display_name'],
                email = parsed_response['email'])
        user.put()
        logging.debug('user created successfully')
               
        logging.debug('creating session for the user')
        # Create session for the user
        session = model.Session(
                id = utils.random(),
                user = user)
        session.put()
        logging.debug('session stored successfully for the user')
        
        StorageByKeyName(
                  model.Credentials, user.username, 'credentials').put(credentials)        
        
        # Set session cookie
        logging.debug('setting session cookie for the user: %s' % session.id)
        self.response.headers.add_header(http.Header.set_cookie, application_params.Http.SESSION_ID + '=' + str(session.id) + '; Path=/')

        # Get info about verified street address
        headers = { http.Header.authorization: http.Header.bearer + ' ' + access_token }
        params = {}
        street_address_path = application_params.IDPConfig.street_address_path
        response = http.get_request(url, street_address_path, headers, params)                
        if response.status != 200:
          logging.error('invalid street address response from the server')
          handle_error(self)
          return        
        response_read = response.read()
        parsed_response = json.loads(response_read)
        idp_address_list = parsed_response['address_list']
        
        values = {
              'user': user,
              'idp_address_list': idp_address_list
        }
        path = os.path.join(os.path.dirname(__file__), '../templates/setup.html')
        self.response.out.write(template.render(path, values))      
        return             
      else:

        # Create session for the existing user
        logging.debug('creating session for the existing user')
        session = model.Session(
                id = utils.random(),
                user = user)
        session.put()
        logging.debug('session created and stored in db')
        
        # Creating credentials for the user
        logging.debug('username: %s' % user.username)
        logging.debug(credentials)
        StorageByKeyName(model.Credentials, user.username, 'credentials').put(credentials)   
        
        # Set session cookie
        logging.debug('setting session cookie for the user: %s' % session.id)
        self.response.headers.add_header(http.Header.set_cookie, application_params.Http.SESSION_ID + '=' + str(session.id) + '; Path=/')         
        self.redirect(application_params.Config.SUCCESS_LOGIN_REDIRECT)          
        return        
      self.redirect("/")

